package com.study.kt._01grammar._02oop

/**
 * 1.在Java中要判断字符串是否为空/空串需要定义StringUtils工具类，而在Kotlin可以为String类扩展一个判空的方法
 * 2.在Java中要为一个类增加一个属性就需要定义一个类继承该类添加属性，在Kotlin中可以使用扩展属性
 *
 */
fun main() {
    val name = ""
    //直接调用扩展函数
    name.isEmpty()

    //扩展函数 静态解析
    val f: EFather = EFather()
    val s: ESon = ESon()
    f.showInfo() //我是father
    s.showInfo() //我是son
    s.showInfo2 {
        println("showInfo2")
    }

    //访问EStu的扩展属性 age
    val stu = EStu("fauks")
    println(stu.age)

    // 测试扩展函数非多态的
    // 虽然BB继承AA，myPrint的参数声明为AA，所以最终打印的还是a
    myPrint(BB())
}

//为字符串提供一个扩展函数 判空
fun String.isEmpty() {
    if (this == null || this.length == 0) {
        println("字符串为空")
    } else {
        println("字符串不为空")
    }
}

//扩展函数的静态解析
//扩展函数对应Java中的静态方法 参数为谁添加的扩展函数就是谁，不同于多态，为父类扩展了函数，即是自类扩展了相同的函数也会调用父类
open class EFather {
    fun showInfo() {
        //如果类中的成员函数与扩展函数同名 则成员函数优先于扩展函数，开发中一般不会出现该情况
        println("成员函数")
    }
}

class ESon : EFather()

//为父类扩展一个函数
fun EFather.showInfo() {
    println("我是father")
}

//为子类扩展与父类相同的方法
//如果函数体只有一行可以简写
fun ESon.showInfo() = println("我是son")

// 为Eson扩展高阶函数
fun ESon.showInfo2(eat: () -> Unit) {
    eat.invoke()
}

//扩展属性
class EStu(var name: String)

//为EStu扩展一个age属性
val EStu.age
    get() = 100 //需要为扩展属性提供get方法

// 扩展方法不支持多态，而且不会修改原有类，调用只取决于对象声明类型，而不是对象实际类型决定
open class AA
class BB : AA()

fun AA.a() {
    println("a")
}

fun BB.a() {
    println("b")
}

fun myPrint(aa: AA) {
    aa.a()
}